package com.example.alternateThread.ree;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class AlternateThread extends Thread {
    ReentrantLock lock = null;
    Condition condition1 = null;
    Condition condition2 = null;
    char ch = 0;

    public AlternateThread(ReentrantLock lock, Condition condition1, Condition condition2, char ch) {
        this.lock = lock;
        this.condition1 = condition1;
        this.condition2 = condition2;
        this.ch = ch;
    }

    @Override
    public void run() {
        // 注意：这里必须是lock代码块把循环体给包裹住，不然可能出现卡死的情况！！！
        lock.lock();
        try {
            for (int i = 0; i < 5; i++) {
                // 一开始先睡
                condition1.await();
                System.out.print(ch);
                // 再把其他线程唤醒
                condition2.signalAll();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ReentrantLock lock = new ReentrantLock();
        Condition condition1 = lock.newCondition();
        Condition condition2 = lock.newCondition();
        Condition condition3 = lock.newCondition();
        // 一开始所有的线程都会先睡
        new AlternateThread(lock, condition1, condition2, 'A').start();
        new AlternateThread(lock, condition2, condition3, 'B').start();
        new AlternateThread(lock, condition3, condition1, 'C').start();
        // 用一个驱动者先唤醒第一个线程
        // 这里特别需要注意的是：要让驱动者在所有线程都睡着后再获取到锁！！！
        Thread.sleep(1000);
        lock.lock();
        try {
            condition1.signalAll();
        } finally {
            lock.unlock();
        }
    }
}
